﻿using System;
using System.Collections.Generic;
using System.Linq;
using Assist;
using Autodesk.Revit.ApplicationServices;
using Autodesk.Revit.DB;
using Autodesk.Revit.Exceptions;
using Autodesk.Revit.UI;
using Autodesk.Revit.UI.Selection;
using YArchitech.Revit;
using YArchitech.Revit.RevitExtension;
using YJKArchMethodLibrary.Utils;

namespace DoorAndWindow
{
	internal class ImpDoorWinInsert
	{
		public bool AddTag
		{
			get
			{
				return this.m_AddTag;
			}
			set
			{
				this.m_AddTag = value;
			}
		}

		public FamilySymbol TagFamilysymbol
		{
			get
			{
				return this.m_TagFamilysymbol;
			}
			set
			{
				this.m_TagFamilysymbol = value;
			}
		}

		public string FirstTagString
		{
			get
			{
				return this.m_FirstTagString;
			}
			set
			{
				this.m_FirstTagString = value;
			}
		}

		public string SecondTagString
		{
			get
			{
				return this.m_SecondTagString;
			}
			set
			{
				this.m_SecondTagString = value;
			}
		}

		public ImpDoorWinInsert(UIApplication uiApp, DoorWinDatum datum)
		{
			this.m_uiApp = uiApp;
			this.m_uiDoc = uiApp.ActiveUIDocument;
			this.m_app = uiApp.Application;
			this.m_doc = this.m_uiDoc.ActiveView.Document;
			this.m_datum = datum;
		}

		public Result PickPtInsert(BuiltInCategory bc, FamilySymbol type, string height)
		{
			List<ElementId> b = AssistFunc.GetAllFamilyInstance(this.m_doc, bc).ToList<ElementId>();
			this.m_uiDoc.RefreshActiveView();
			if (!this.PromptForFamilyInstancePlacement(type))
			{
				return Autodesk.Revit.UI.Result.Failed;
			}
			List<ElementId> a = AssistFunc.GetAllFamilyInstance(this.m_doc, bc).ToList<ElementId>();
			List<ElementId> list = AssistFunc.SubCollection(a, b).ToList<ElementId>();
			foreach (ElementId id in list)
			{
				using (Transaction transaction = new Transaction(this.m_doc, "SET"))
				{
					try
					{
						transaction.Start();
						Element element = RevitVersionFuncs.GetElement(this.m_doc, id);
						Parameter parameter = element.get_Parameter(BuiltInParameter.INSTANCE_SILL_HEIGHT_PARAM);
						parameter.Set(AssistFunc.mmToFeet(Convert.ToDouble(height)));
						this.m_doc.Regenerate();
						FilteredElementCollector filteredElementCollector = new FilteredElementCollector(this.m_doc);
						ElementIntersectsElementFilter elementIntersectsElementFilter = new ElementIntersectsElementFilter(element, false);
						filteredElementCollector.WherePasses(elementIntersectsElementFilter);
						filteredElementCollector.Excluding(new List<ElementId>
						{
							element.Id
						});
						try
						{
							foreach (Element element2 in filteredElementCollector)
							{
                                if (element2.Category.Id.IntegerValue == -2000100 || element2.Category.Id.IntegerValue == (int)BuiltInCategory.OST_Doors || element2.Category.Id.IntegerValue == (int)BuiltInCategory.OST_Windows)
								{
									this.m_doc.DeleteElement(element);
									this.m_doc.Regenerate();
									TaskDialog.Show("插入异常", "与已有对象重叠,无法布置！");
								}
							}
						}
						catch
						{
						}
						transaction.Commit();
						this.DoInsertTag(element as FamilyInstance);
					}
					catch (Exception ex)
					{
						transaction.Commit();
						throw ex;
					}
				}
			}
			return Autodesk.Revit.UI.Result.Succeeded;
		}

		private bool PromptForFamilyInstancePlacement(FamilySymbol jigType)
		{
			bool result;
			try
			{
				this.m_uiDoc.PromptForFamilyInstancePlacement(jigType);
				result = true;
			}
			catch (Autodesk.Revit.Exceptions.OperationCanceledException)
			{
				result = true;
			}
			catch (Exception)
			{
				result = false;
			}
			return result;
		}

		public Result EqualInsert(BuiltInCategory bc, FamilySymbol type, double height, ref string message)
		{
			while (this.EqualSingleInsert(bc, type, height, ref message) == null)
			{
			}
			return Autodesk.Revit.UI.Result.Cancelled;
		}

		public Result EqualSingleInsert(BuiltInCategory bc, FamilySymbol type, double height, ref string message)
		{
			Result result;
			try
			{
				Wall wall = null;
				XYZ xyz = null;
				XYZ isSelPositiveSideline = null;
				if (this.SelectWallSideline(ref wall, ref xyz, ref isSelPositiveSideline, ref message) != null)
				{
					result = Autodesk.Revit.UI.Result.Failed;
				}
				else
				{
					XYZ startPt = WallAssistFunc.GetStartPt(wall);
					XYZ endPt = WallAssistFunc.GetEndPt(wall);
					xyz = new XYZ(xyz.X, xyz.Y, startPt.Z);
					this.SolveColumn(wall, xyz, ref startPt, ref endPt);
					XYZ nearbyStart = null;
					Curve curve = (wall.Location as LocationCurve).Curve;
					if (curve is Line)
					{
						curve = Line.CreateBound(startPt, endPt);
					}
					else
					{
						Arc curve2 = curve as Arc;
						curve = this.CreateArc(startPt, endPt, curve2);
					}
					bool isWithin = true;
					if (bc == BuiltInCategory.OST_Doors)
					{
						Result result2 = this.IsNearbyWallStartByUser(curve, wall.Width, isSelPositiveSideline, ref nearbyStart, xyz, ref isWithin);
						if (result2 != null)
						{
							return result2;
						}
					}
					int nEqualNum = this.m_datum.m_nEqualNum;
					double dDoorWidth = type.get_Parameter(BuiltInParameter.CASEWORK_WIDTH).AsDouble();
					List<XYZ> wallEqualPoints = this.GetWallEqualPoints(curve, startPt, endPt, dDoorWidth, nEqualNum, height);
					List<Element> insertDirection = this.DoInsert(wallEqualPoints, type, wall, height, ref message, isSelPositiveSideline, nearbyStart, isWithin);
					result = this.SetInsertDirection(insertDirection);
				}
			}
			catch (Autodesk.Revit.Exceptions.OperationCanceledException)
			{
				result = Autodesk.Revit.UI.Result.Cancelled;
			}
			catch (Exception ex)
			{
				message = ex.Message;
				result = Autodesk.Revit.UI.Result.Failed;
			}
			return result;
		}

		private void SolveColumn(Wall wall, XYZ ptPick, ref XYZ ptStart, ref XYZ ptEnd)
		{
			List<Element> wallsJoinedElement = this.GetWallsJoinedElement(wall);
			List<Element> wallsIntersectElement = this.GetWallsIntersectElement(wall);
			List<Element> list = new List<Element>();
			list.AddRange(wallsJoinedElement);
			list.AddRange(wallsIntersectElement);
			if (list.Count != 0)
			{
				List<XYZ> list2 = new List<XYZ>();
				Curve curve = (wall.Location as LocationCurve).Curve;
				List<XYZ> list3 = (from col in list
				select (col.Location as LocationPoint).Point).ToList<XYZ>();
				foreach (XYZ xyz in list3)
				{
					list2.Add(curve.Project(xyz).XYZPoint);
				}
				XYZ xyzpoint = curve.Project(ptPick).XYZPoint;
				ptStart = this.GetLayEndPoint(ptStart, xyzpoint, list2, curve);
				ptEnd = this.GetLayEndPoint(ptEnd, xyzpoint, list2, curve);
			}
		}

		private List<Element> GetWallsJoinedElement(Element wall)
		{
			List<Element> list = new List<Element>();
			ICollection<ElementId> joinedElements = JoinGeometryUtils.GetJoinedElements(this.m_doc, wall);
			foreach (ElementId elementId in joinedElements)
			{
				Element element = this.m_doc.GetElement(elementId);
				if (element is FamilyInstance)
				{
					FamilyInstance familyInstance = element as FamilyInstance;
					if (familyInstance.Category.Id.IntegerValue == -2000100 || familyInstance.Category.Id.IntegerValue == -2001330)
					{
						list.Add(familyInstance);
					}
				}
			}
			return list;
		}

		private List<Element> GetWallsIntersectElement(Element wall)
		{
			FilteredElementCollector filteredElementCollector = new FilteredElementCollector(this.m_doc);
			filteredElementCollector.OfClass(typeof(FamilyInstance)).OfCategory(BuiltInCategory.OST_Columns);
			FilteredElementCollector filteredElementCollector2 = new FilteredElementCollector(this.m_doc);
			filteredElementCollector2.OfClass(typeof(FamilyInstance)).OfCategory(BuiltInCategory.OST_StructuralColumns);
			ElementIntersectsElementFilter elementIntersectsElementFilter = new ElementIntersectsElementFilter(wall);
			filteredElementCollector.WherePasses(elementIntersectsElementFilter);
			filteredElementCollector2.WherePasses(elementIntersectsElementFilter);
			List<Element> list = new List<Element>();
			foreach (Element item in filteredElementCollector)
			{
				list.Add(item);
			}
			foreach (Element item2 in filteredElementCollector2)
			{
				list.Add(item2);
			}
			return list;
		}

		private XYZ GetLayEndPoint(XYZ ptEnd, XYZ ptOnCurve, List<XYZ> pts, Curve curve)
		{
			if (curve is Arc)
			{
				Arc arc = this.CreateArc(ptOnCurve, ptEnd, curve);
				List<XYZ> list = new List<XYZ>();
				list.Add(ptEnd);
				foreach (XYZ xyz in pts)
				{
					if (arc.Distance(xyz) < 0.001)
					{
						list.Add(xyz);
					}
				}
				List<Arc> list2 = new List<Arc>();
				foreach (XYZ ptEnd2 in list)
				{
					Arc item = this.CreateArc(ptOnCurve, ptEnd2, curve);
					list2.Add(item);
				}
				List<Arc> list3 = (from p in list2
				orderby p.Length
				select p).ToList<Arc>();
				if (list3.Count > 0)
				{
					return list3[0].GetEndPoint(1);
				}
			}
			else
			{
				Line line = Line.CreateBound(ptOnCurve, ptEnd);
				List<XYZ> list4 = new List<XYZ>();
				list4.Add(ptEnd);
				foreach (XYZ xyz2 in pts)
				{
					if (line.Distance(xyz2) < 0.001)
					{
						list4.Add(xyz2);
					}
				}
				List<XYZ> list5 = (from p in list4
				orderby p.DistanceTo(ptOnCurve)
				select p).ToList<XYZ>();
				if (list5.Count > 0)
				{
					return list5[0];
				}
			}
			return ptEnd;
		}

		private Arc CreateArc(XYZ ptStart, XYZ ptEnd, Curve curve)
		{
			IntersectionResult intersectionResult = curve.Project(ptStart);
			IntersectionResult intersectionResult2 = curve.Project(ptEnd);
			double num = (intersectionResult.Parameter + intersectionResult2.Parameter) * 0.5;
			XYZ xyz = curve.Evaluate(num, false);
			return Arc.Create(ptStart, ptEnd, xyz);
		}

		private Result SetInsertDirection(List<Element> elems)
		{
			foreach (Element element in elems)
			{
				FamilyInstance familyInstance = (FamilyInstance)element;
				this.DoInsertTag(familyInstance);
			}
			return Autodesk.Revit.UI.Result.Succeeded;
		}

		public Result GridLineEqualInsert(BuiltInCategory bc, FamilySymbol type, double height, ref string message)
		{
			while (this.GridLineEqualSingleInsert(bc, type, height, ref message) == null)
			{
			}
			return Autodesk.Revit.UI.Result.Cancelled;
		}

		public Result GridLineEqualSingleInsert(BuiltInCategory bc, FamilySymbol type, double height, ref string message)
		{
			Result result;
			try
			{
				Wall wall = null;
				XYZ xyz = null;
				XYZ isSelPositiveSideline = null;
				if (this.SelectWallSideline(ref wall, ref xyz, ref isSelPositiveSideline, ref message) != null)
				{
					result = Autodesk.Revit.UI.Result.Failed;
				}
				else
				{
					XYZ startPt = WallAssistFunc.GetStartPt(wall);
					xyz = new XYZ(xyz.X, xyz.Y, startPt.Z);
					XYZ xyz2 = new XYZ();
					XYZ xyz3 = new XYZ();
					List<KeyValuePair<Grid, XYZ>> wallGrids = this.GetWallGrids(xyz, wall);
					if (wallGrids.Count != 2)
					{
						throw new Exception();
					}
					XYZ value = wallGrids[0].Value;
					XYZ value2 = wallGrids[1].Value;
					xyz2 = value;
					xyz3 = value2;
					this.SolveColumn(wall, xyz, ref xyz2, ref xyz3);
					XYZ nearbyStart = null;
					Curve curve = (wall.Location as LocationCurve).Curve;
					if (curve is Line)
					{
						curve = Line.CreateBound(xyz2, xyz3);
					}
					else
					{
						Arc curve2 = curve as Arc;
						curve = this.CreateArc(xyz2, xyz3, curve2);
					}
					bool isWithin = true;
					if (bc == BuiltInCategory.OST_Doors)
					{
						Result result2 = this.IsNearbyWallStartByUser(curve, wall.Width, isSelPositiveSideline, ref nearbyStart, xyz, ref isWithin);
						if (result2 != null)
						{
							return result2;
						}
					}
					int nEqualNum = this.m_datum.m_nEqualNum;
					double dDoorWidth = type.get_Parameter(BuiltInParameter.CASEWORK_WIDTH).AsDouble();
					List<XYZ> wallEqualPoints = this.GetWallEqualPoints(curve, xyz2, xyz3, dDoorWidth, nEqualNum, height, xyz);
					List<Element> insertDirection = this.DoInsert(wallEqualPoints, type, wall, height, ref message, isSelPositiveSideline, nearbyStart, isWithin);
					result = this.SetInsertDirection(insertDirection);
				}
			}
			catch (Autodesk.Revit.Exceptions.OperationCanceledException)
			{
				result = Autodesk.Revit.UI.Result.Cancelled;
			}
			catch (Exception ex)
			{
				message = ex.Message;
				result = Autodesk.Revit.UI.Result.Failed;
			}
			return result;
		}

		private List<KeyValuePair<Grid, XYZ>> GetWallGrids(XYZ pickPoint, Wall wall)
		{
			List<KeyValuePair<Grid, XYZ>> list = new List<KeyValuePair<Grid, XYZ>>();
			Curve curve = ((LocationCurve)wall.Location).Curve;
			XYZ wallPick = curve.Project(pickPoint).XYZPoint;
			List<Grid> allGrids = this.GetAllGrids();
			Dictionary<Grid, XYZ> intersectionGrids = this.GetIntersectionGrids(allGrids, curve, wallPick);
			if (intersectionGrids.Count < 2)
			{
				return list;
			}
			List<KeyValuePair<Grid, XYZ>> list2 = new List<KeyValuePair<Grid, XYZ>>(intersectionGrids);
			list2.Sort((KeyValuePair<Grid, XYZ> s1, KeyValuePair<Grid, XYZ> s2) => s1.Value.DistanceTo(wallPick).CompareTo(s2.Value.DistanceTo(wallPick)));
			KeyValuePair<Grid, XYZ> item = list2.First<KeyValuePair<Grid, XYZ>>();
			KeyValuePair<Grid, XYZ> item2 = default(KeyValuePair<Grid, XYZ>);
			if (curve is Line)
			{
				XYZ xyz = (wallPick - item.Value).Normalize();
				for (int i = 1; i < list2.Count; i++)
				{
					XYZ xyz2 = (list2[i].Value - wallPick).Normalize();
					if (xyz.IsAlmostEqualTo(xyz2))
					{
						item2 = list2[i];
						break;
					}
				}
				if (item2.Key == null)
				{
					return list;
				}
				list.Add(item);
				list.Add(item2);
			}
			else if (curve is Arc)
			{
				Arc arc = curve as Arc;
				XYZ hyendPoint = arc.GetEndPoint(0);
				XYZ hyendPoint2 = arc.GetEndPoint(1);
				bool isAnticlockwise = true;
				if (arc.Normal.IsAlmostEqualTo(new XYZ(0.0, 0.0, -1.0)))
				{
					isAnticlockwise = false;
				}
				double bulge = Geometry.GetBulge(hyendPoint, hyendPoint2, arc.Center, isAnticlockwise);
				XYZ xyz3 = null;
				Geometry.GetCenterWithBulge(hyendPoint, hyendPoint2, bulge, ref xyz3);
				if (xyz3 == null)
				{
					throw new Exception();
				}
				XYZ xyz4 = (wallPick - xyz3).Normalize();
				Dictionary<Grid, double> dictionary = new Dictionary<Grid, double>();
				for (int j = 0; j < list2.Count; j++)
				{
					XYZ xyz5 = (list2[j].Value - xyz3).Normalize();
					double value = xyz4.AngleOnPlaneTo(xyz5, XYZ.BasisZ);
					dictionary.Add(list2[j].Key, value);
				}
				List<KeyValuePair<Grid, double>> list3 = new List<KeyValuePair<Grid, double>>(dictionary);
				list3.Sort((KeyValuePair<Grid, double> s1, KeyValuePair<Grid, double> s2) => s1.Value.CompareTo(s2.Value));
				if (list3[0].Value < Math.PI && list3[list3.Count - 1].Value > Math.PI)
				{
					for (int k = 0; k < list2.Count; k++)
					{
						if (list2[k].Key == list3[0].Key)
						{
							list.Add(list2[k]);
						}
						else if (list2[k].Key == list3[list3.Count - 1].Key)
						{
							list.Add(list2[k]);
						}
					}
				}
			}
			return list;
		}

		private Dictionary<Grid, XYZ> GetIntersectionGrids(List<Grid> intersectionGrids, Curve wCurve, XYZ wallPick)
		{
			Curve curve = null;
			if (wCurve is Line)
			{
				XYZ endPoint = wCurve.GetEndPoint(0);
				XYZ endPoint2 = wCurve.GetEndPoint(1);
				XYZ xyz = (endPoint2 - endPoint).Normalize();
				XYZ xyz2 = endPoint + -xyz * 0.001;
				XYZ xyz3 = endPoint2 + xyz * 0.001;
				curve = Line.CreateBound(xyz2, xyz3);
			}
			else
			{
				curve = wCurve;
			}
			Dictionary<Grid, XYZ> dictionary = new Dictionary<Grid, XYZ>();
			foreach (Grid grid in intersectionGrids)
			{
				Curve curve2 = null;
				Curve curve3 = grid.Curve;
				if (curve3 is Line)
				{
					curve2 = YJKLineEx.YJKGetBound(new XYZ(grid.Curve.GetEndPoint(0).X, grid.Curve.GetEndPoint(0).Y, wCurve.GetEndPoint(0).Z), new XYZ(grid.Curve.GetEndPoint(1).X, grid.Curve.GetEndPoint(1).Y, wCurve.GetEndPoint(0).Z));
				}
				else if (curve3 is Arc)
				{
					XYZ hyendPoint = curve3.GetEndPoint(0);
					XYZ hyendPoint2 = curve3.GetEndPoint(1);
					XYZ arcMidPoint = ArcAssistFunc.GetArcMidPoint(curve3 as Arc);
					curve2 = this.m_uiApp.Application.CreatYJKArc(new XYZ(hyendPoint.X, hyendPoint.Y, wCurve.GetEndPoint(0).Z), new XYZ(hyendPoint2.X, hyendPoint2.Y, wCurve.GetEndPoint(0).Z), new XYZ(arcMidPoint.X, arcMidPoint.Y, wCurve.GetEndPoint(0).Z));
				}
				new IntersectionResultArray();
				IntersectionResultArray intersectionResultArray;
				SetComparisonResult setComparisonResult = curve2.Intersect(curve, out intersectionResultArray);
				if (setComparisonResult == SetComparisonResult.Overlap && intersectionResultArray.Size >= 1)
				{
					XYZ value = null;
					if (intersectionResultArray.Size > 1)
					{
						List<XYZ> list = new List<XYZ>();
						foreach (object obj in intersectionResultArray)
						{
							IntersectionResult intersectionResult = (IntersectionResult)obj;
							IntersectionResult intersectionResult2 = intersectionResult;
							XYZ xyzpoint = intersectionResult2.XYZPoint;
							list.Add(xyzpoint);
						}
						list.Sort((XYZ s1, XYZ s2) => s1.DistanceTo(wallPick).CompareTo(s2.DistanceTo(wallPick)));
						value = list[0];
					}
					else
					{
						foreach (object obj2 in intersectionResultArray)
						{
							IntersectionResult intersectionResult3 = (IntersectionResult)obj2;
							IntersectionResult intersectionResult4 = intersectionResult3;
							XYZ xyzpoint2 = intersectionResult4.XYZPoint;
							value = xyzpoint2;
						}
					}
					if (!dictionary.Keys.Contains(grid))
					{
						dictionary.Add(grid, value);
					}
				}
			}
			return dictionary;
		}

		private List<Grid> GetAllGrids()
		{
			List<Grid> list = new List<Grid>();
			FilteredElementCollector filteredElementCollector = new FilteredElementCollector(this.m_doc);
			IList<Element> list2 = filteredElementCollector.OfClass(typeof(Grid)).ToElements();
			foreach (Element element in list2)
			{
				Grid grid = element as Grid;
				if (grid != null)
				{
					list.Add(grid);
				}
			}
			return list;
		}

		public Result ButtressInsert(BuiltInCategory bc, FamilySymbol type, double height, ref string message)
		{
			double dButtressWidth = this.m_datum.m_dButtressWidth;
			Result result;
			for (;;)
			{
				Transaction transaction = new Transaction(this.m_doc, "AddDoorWin");
				try
				{
					transaction.Start();
					Wall host = null;
					XYZ xyz = null;
					XYZ xyz2 = null;
					if (this.SelectWallSideline(ref host, ref xyz, ref xyz2, ref message) == null)
					{
						XYZ ptPick = new XYZ(xyz.X, xyz.Y, 0.0);
						XYZ pt = null;
						XYZ pt2 = null;
						Element element = this.DoInsert(dButtressWidth, type, host, ptPick, height, bc, ref pt, ref pt2);
						transaction.Commit();
						if (element.IsValidObject)
						{
							Transaction transaction2 = new Transaction(this.m_doc, "ChangeOrientation");
							transaction2.Start();
							FamilyInstance familyInstance = element as FamilyInstance;
							familyInstance.flipFacing();
							familyInstance.flipFacing();
							if (familyInstance.CanFlipFacing && !Geometry.IsEqual(pt2, familyInstance.FacingOrientation))
							{
								familyInstance.flipFacing();
							}
							if (familyInstance.CanFlipHand && !Geometry.IsEqual(pt, familyInstance.HandOrientation))
							{
								familyInstance.flipHand();
							}
							transaction2.Commit();
							this.DoInsertTag(familyInstance);
						}
						continue;
					}
					transaction.RollBack();
					result = Autodesk.Revit.UI.Result.Failed;
				}
				catch (Autodesk.Revit.Exceptions.OperationCanceledException)
				{
					transaction.RollBack();
					result = Autodesk.Revit.UI.Result.Succeeded;
				}
				catch (Exception ex)
				{
					transaction.RollBack();
					message = ex.Message;
					result = Autodesk.Revit.UI.Result.Failed;
				}
				break;
			}
			return result;
		}

		public ElementId GetCurrentLevelId(ref string message)
		{
			Level currentViewLevel = AssistFunc.GetCurrentViewLevel(this.m_doc);
			if (currentViewLevel == null)
			{
				message = "当前激活的View不是平面的View！";
				return null;
			}
			return currentViewLevel.get_Parameter(BuiltInParameter.ID_PARAM).AsElementId();
		}

		private List<XYZ> GetWallEqualPoints(Curve curve, XYZ pt1, XYZ pt2, double dDoorWidth, int count, double height, XYZ pickPoint)
		{
			List<XYZ> list = null;
			int num = count + 1;
			Line line = curve as Line;
			if (line != null)
			{
				double num2 = pt1.DistanceTo(pt2) + dDoorWidth;
				XYZ xyz = (pt2 - pt1).Normalize();
				double num3 = num2 / (double)num;
				list = new List<XYZ>();
				for (int i = 1; i < num; i++)
				{
					XYZ xyz2 = pt1 + xyz * (num3 * (double)i - dDoorWidth / 2.0);
					XYZ item = new XYZ(xyz2.X, xyz2.Y, AssistFunc.mmToFeet(height));
					list.Add(item);
				}
			}
			Arc arc = curve as Arc;
			if (arc != null)
			{
				XYZ center = arc.Center;
				XYZ xyzpoint = arc.Project(new XYZ(pickPoint.X, pickPoint.Y, pt1.Z)).XYZPoint;
				arc = this.m_uiApp.Application.CreatYJKArc(pt1, pt2, xyzpoint);
				double hyendParameter = arc.GetYJKEndParameter(0);
				double hyendParameter2 = arc.GetYJKEndParameter(1);
				double num4 = dDoorWidth / arc.Radius;
				double num5 = (hyendParameter2 - hyendParameter + num4) / (double)num;
				XYZ normal = arc.Normal;
				Transform transform = RevitVersionFuncs.CreateRotationAtPoint(normal, num5 - num4 / 2.0, center);
				list = new List<XYZ>();
				XYZ xyz3 = transform.OfPoint(pt1);
				list.Add(xyz3);
				Transform transform2 = RevitVersionFuncs.CreateRotationAtPoint(normal, num5, center);
				for (int j = 1; j < count; j++)
				{
					xyz3 = transform2.OfPoint(xyz3);
					XYZ item2 = new XYZ(xyz3.X, xyz3.Y, AssistFunc.mmToFeet(height));
					list.Add(item2);
				}
			}
			return list;
		}

		private List<XYZ> GetWallEqualPoints(Curve curve, XYZ pt1, XYZ pt2, double dDoorWidth, int count, double height)
		{
			List<XYZ> list = null;
			int num = count + 1;
			Line line = curve as Line;
			if (line != null)
			{
				double num2 = pt1.DistanceTo(pt2) + dDoorWidth;
				XYZ xyz = (pt2 - pt1).Normalize();
				double num3 = num2 / (double)num;
				list = new List<XYZ>();
				for (int i = 1; i < num; i++)
				{
					XYZ xyz2 = pt1 + xyz * (num3 * (double)i - dDoorWidth / 2.0);
					XYZ item = new XYZ(xyz2.X, xyz2.Y, AssistFunc.mmToFeet(height));
					list.Add(item);
				}
			}
			Arc arc = curve as Arc;
			if (arc != null)
			{
				XYZ center = arc.Center;
				double hyendParameter = arc.GetYJKEndParameter(0);
				double hyendParameter2 = arc.GetYJKEndParameter(1);
				double num4 = dDoorWidth / arc.Radius;
				double num5 = (hyendParameter2 - hyendParameter + num4) / (double)num;
				XYZ normal = arc.Normal;
				Transform transform = RevitVersionFuncs.CreateRotationAtPoint(normal, num5 - num4 / 2.0, center);
				list = new List<XYZ>();
				XYZ xyz3 = transform.OfPoint(pt1);
				list.Add(xyz3);
				Transform transform2 = RevitVersionFuncs.CreateRotationAtPoint(normal, num5, center);
				for (int j = 1; j < count; j++)
				{
					xyz3 = transform2.OfPoint(xyz3);
					XYZ item2 = new XYZ(xyz3.X, xyz3.Y, AssistFunc.mmToFeet(height));
					list.Add(item2);
				}
			}
			return list;
		}

		private Element DoInsert(XYZ pt, FamilySymbol type, Wall host, double height, ref string message, XYZ isSelPositiveSideline, XYZ nearbyStart, bool isWithin)
		{
			FamilyInstance familyInstance = null;
			ElementId currentLevelId = this.GetCurrentLevelId(ref message);
			if (currentLevelId == null)
			{
				return null;
			}
			Transaction transaction = new Transaction(this.m_doc, "temp");
			transaction.Start();
			XYZ xyz = new XYZ(pt.X, pt.Y, AssistFunc.GetCurrentViewLevel(this.m_uiDoc.Document).Elevation + AssistFunc.mmToFeet(height));
			try
			{
				if (!type.IsActive)
				{
					type.Activate();
					this.m_doc.Regenerate();
				}
				familyInstance = this.m_doc.Create.NewFamilyInstance(xyz, type, host, AssistFunc.GetCurrentViewLevel(this.m_uiDoc.Document), 0);
				this.m_doc.Regenerate();
				familyInstance.flipFacing();
				familyInstance.flipFacing();
				Curve curve = (host.Location as LocationCurve).Curve;
				if (familyInstance.CanFlipFacing)
				{
					if (curve is Arc)
					{
						Arc arc = curve as Arc;
						isSelPositiveSideline = (arc.Center - new XYZ(xyz.X, xyz.Y, arc.Center.Z)).Normalize();
						if (!isWithin)
						{
							isSelPositiveSideline = -isSelPositiveSideline;
						}
					}
					if (!familyInstance.FacingOrientation.IsAlmostEqualTo(isSelPositiveSideline))
					{
						familyInstance.flipFacing();
						nearbyStart = -familyInstance.HandOrientation;
					}
					else
					{
						nearbyStart = familyInstance.HandOrientation;
					}
				}
				if (familyInstance.CanFlipHand)
				{
					if (curve is Arc)
					{
						XYZ xyz2 = isSelPositiveSideline.CrossProduct(nearbyStart).Normalize();
						XYZ xyz3 = familyInstance.FacingOrientation.CrossProduct(familyInstance.HandOrientation).Normalize();
						if (!xyz2.IsAlmostEqualTo(xyz3))
						{
							familyInstance.flipHand();
						}
					}
					else if (!familyInstance.HandOrientation.IsAlmostEqualTo(nearbyStart))
					{
						familyInstance.flipHand();
					}
				}
				transaction.Commit();
			}
			catch
			{
				transaction.RollBack();
			}
			return familyInstance;
		}

		private List<Element> DoInsert(List<XYZ> arPts, FamilySymbol doorType, Wall host, double height, ref string message, XYZ isSelPositiveSideline, XYZ nearbyStart, bool isWithin)
		{
			List<Element> list = new List<Element>();
			foreach (XYZ pt in arPts)
			{
				Element element = this.DoInsert(pt, doorType, host, height, ref message, isSelPositiveSideline, nearbyStart, isWithin);
				if (element != null)
				{
					list.Add(element);
				}
			}
			return list;
		}

		private Element DoInsert(double dButtWidth, FamilySymbol doorType, Wall host, XYZ ptPick, double height, BuiltInCategory cate, ref XYZ handOrientation, ref XYZ faceOrientation)
		{
			Level currentViewLevel = AssistFunc.GetCurrentViewLevel(this.m_doc);
			if (currentViewLevel == null)
			{
				return null;
			}
			currentViewLevel.get_Parameter(BuiltInParameter.ID_PARAM).AsElementId();
			double num = AssistFunc.feetToMM(doorType.get_Parameter(BuiltInParameter.CASEWORK_WIDTH).AsDouble());
			IList<FamilyInstance> wallAssoDoorWins = WallAssistFunc.GetWallAssoDoorWins(this.m_doc, host, BuiltInCategory.OST_Doors, currentViewLevel);
			XYZ xyz = null;
			XYZ xyz2 = null;
			XYZ startPt = WallAssistFunc.GetStartPt(host);
			XYZ endPt = WallAssistFunc.GetEndPt(host);
			IList<XYZ> list = new List<XYZ>();
			list.Add(startPt);
			list.Add(endPt);
			if (wallAssoDoorWins != null)
			{
				for (int i = 0; i < wallAssoDoorWins.Count; i++)
				{
					FamilyInstance instance = wallAssoDoorWins.ElementAt(i);
					list.Add(DoorWinAssistFunc.GetBoundPt(instance, host, 0));
					list.Add(DoorWinAssistFunc.GetBoundPt(instance, host, 1));
				}
			}
			IList<FamilyInstance> wallAssoDoorWins2 = WallAssistFunc.GetWallAssoDoorWins(this.m_doc, host, BuiltInCategory.OST_Windows, currentViewLevel);
			if (wallAssoDoorWins2 != null)
			{
				for (int j = 0; j < wallAssoDoorWins2.Count; j++)
				{
					FamilyInstance instance2 = wallAssoDoorWins2.ElementAt(j);
					list.Add(DoorWinAssistFunc.GetBoundPt(instance2, host, 0));
					list.Add(DoorWinAssistFunc.GetBoundPt(instance2, host, 1));
				}
			}
			ElementCategoryFilter elementCategoryFilter = new ElementCategoryFilter(BuiltInCategory.OST_Walls);
			FilteredElementCollector filteredElementCollector = new FilteredElementCollector(this.m_doc, this.m_doc.ActiveView.Id);
			IList<Element> list2 = filteredElementCollector.WherePasses(elementCategoryFilter).WhereElementIsNotElementType().ToElements();
			foreach (Element element in list2)
			{
				if (element.Id != host.Id)
				{
					Wall wall = RevitVersionFuncs.GetElement(this.m_doc, element.Id) as Wall;
					if (wall != null)
					{
						IList<XYZ> list3 = ElementAssistFunc.Intersect(wall, host);
						foreach (XYZ item in list3)
						{
							list.Add(item);
						}
					}
				}
			}
            BuiltInCategory builtInCategory = (BuiltInCategory)(-2000100);
			ElementCategoryFilter elementCategoryFilter2 = new ElementCategoryFilter(builtInCategory);
			FilteredElementCollector filteredElementCollector2 = new FilteredElementCollector(this.m_doc, this.m_doc.ActiveView.Id);
			IList<Element> list4 = filteredElementCollector2.OfClass(typeof(FamilyInstance)).WherePasses(elementCategoryFilter2).ToElements();
			foreach (Element otherElem in list4)
			{
				IList<XYZ> list5 = ElementAssistFunc.Intersect(host, otherElem);
				foreach (XYZ item2 in list5)
				{
					list.Add(item2);
				}
			}
			double num2 = 10000000.0;
			foreach (XYZ xyz3 in list)
			{
				double length = (ptPick - xyz3).GetLength();
				if (length < num2)
				{
					num2 = length;
					xyz2 = xyz3;
				}
			}
			if (WallAssistFunc.GetWallCurveType(host) == WallCurveType.eLineWall)
			{
				Line line = WallAssistFunc.GetWallCurve(host) as Line;
				XYZ xyz4 = Geometry.CalculateFootPoint(line, ptPick);
				faceOrientation = (ptPick - xyz4).Normalize();
				XYZ xyz5 = Geometry.CalculateFootPoint(line, xyz2);
				handOrientation = (xyz5 - xyz4).Normalize();
				xyz = xyz5 - handOrientation * AssistFunc.mmToFeet(dButtWidth + num / 2.0);
			}
			else if (WallAssistFunc.GetWallCurveType(host) == WallCurveType.eArcWall)
			{
				Arc arc = WallAssistFunc.GetWallCurve(host) as Arc;
				XYZ xyz6 = Geometry.CalculateFootPoint(arc, ptPick);
				double val = (xyz2 - arc.Center).AngleOnPlaneTo(ptPick - arc.Center, XYZ.BasisZ);
				XYZ axis = -XYZ.BasisZ;
				double num3 = AssistFunc.mmToFeet(dButtWidth + num / 2.0) / arc.Radius;
				if (Geometry.LessThan(Math.PI*.5, val))
				{
					num3 = -num3;
					axis = XYZ.BasisZ;
				}
				Transform transform = RevitVersionFuncs.CreateRotationAtPoint(XYZ.BasisZ, num3, arc.Center);
				xyz = transform.OfPoint(xyz2);
				XYZ xyz7 = (xyz - arc.Center).Normalize();
				faceOrientation = xyz7;
				double val2 = ptPick.DistanceTo(arc.Center);
				double val3 = xyz6.DistanceTo(arc.Center);
				if (Geometry.LessThan(val2, val3))
				{
					faceOrientation = -faceOrientation;
				}
				handOrientation = Geometry.RotateTo(xyz7, Math.PI*.5, axis);
			}
			XYZ xyz8 = new XYZ(xyz.X, xyz.Y, AssistFunc.GetCurrentViewLevel(this.m_doc).Elevation + AssistFunc.mmToFeet(height));
			UnifiedModified.ActivateFamilySymbol(doorType);
			return this.m_doc.Create.NewFamilyInstance(xyz8, doorType, host, AssistFunc.GetCurrentViewLevel(this.m_doc), 0);
		}

		private Result SelectWallSideline(ref Wall wall, ref XYZ pickPoint, ref XYZ selUpDownDir, ref string message)
		{
			Reference reference = null;
			Selection selection = this.m_uiDoc.Selection;
			try
			{
				reference = selection.PickObject(Autodesk.Revit.UI.Selection.ObjectType.Face, "请选择要对齐的墙边");
			}
			catch (Exception)
			{
				return Autodesk.Revit.UI.Result.Cancelled;
			}
			if (reference == null)
			{
				message = "无法得到墙体边线！";
				return Autodesk.Revit.UI.Result.Failed;
			}
			pickPoint = reference.GlobalPoint;
			Element element = this.m_doc.GetElement(reference);
			Face face = element.GetGeometryObjectFromReference(reference) as Face;
			wall = (element as Wall);
			if (null == face && wall == null)
			{
				message = "无法得到墙体边线！";
				return Autodesk.Revit.UI.Result.Failed;
			}
			LocationCurve locationCurve = wall.Location as LocationCurve;
			Curve curve = locationCurve.Curve;
			if (curve.GetType() == typeof(Line))
			{
				Line line = curve as Line;
				XYZ xyzpoint = line.Project(pickPoint).XYZPoint;
				selUpDownDir = (new XYZ(pickPoint.X, pickPoint.Y, 0.0) - new XYZ(xyzpoint.X, xyzpoint.Y, 0.0)).Normalize();
			}
			else if (!(curve.GetType() == typeof(Arc)))
			{
				message = "无法处理的墙类型！";
				return Autodesk.Revit.UI.Result.Failed;
			}
			return Autodesk.Revit.UI.Result.Succeeded;
		}

		private XYZ RotateTo(XYZ List, double angle, XYZ axis)
		{
			Transform transform = RevitVersionFuncs.CreateRotationAtPoint(axis, angle, new XYZ(0.0, 0.0, 0.0));
			return this.TransformPoint(List, transform);
		}

		private XYZ TransformPoint(XYZ point, Transform transform)
		{
			double x = point.X;
			double y = point.Y;
			double z = point.Z;
			XYZ xyz = transform.get_Basis(0);
			XYZ xyz2 = transform.get_Basis(1);
			XYZ xyz3 = transform.get_Basis(2);
			XYZ origin = transform.Origin;
			double num = x * xyz.X + y * xyz2.X + z * xyz3.X + origin.X;
			double num2 = x * xyz.Y + y * xyz2.Y + z * xyz3.Y + origin.Y;
			double num3 = x * xyz.Z + y * xyz2.Z + z * xyz3.Z + origin.Z;
			return new XYZ(num, num2, num3);
		}

		private Result IsNearbyWallStartByUser(Curve wallAxis, double wallThickness, XYZ isSelPositiveSideline, ref XYZ nearbyStart, XYZ pickPoint, ref bool isWithin)
		{
			XYZ xyz = null;
			XYZ xyz2 = null;
			double num = AssistFunc.mmToFeet(500.0);
			double num2 = AssistFunc.mmToFeet(1500.0);
			XYZ hyendPoint = wallAxis.GetEndPoint(0);
			XYZ hyendPoint2 = wallAxis.GetEndPoint(1);
			XYZ xyz3;
			if (wallAxis.GetType() == typeof(Line))
			{
				xyz3 = (hyendPoint + hyendPoint2) / 2.0;
				XYZ xyz4 = isSelPositiveSideline * (wallThickness / 2.0 + num);
				xyz3 += xyz4;
				xyz = this.RotateTo(isSelPositiveSideline, -Math.PI*.5, XYZ.BasisZ);
				xyz2 = this.RotateTo(isSelPositiveSideline, Math.PI*.5, XYZ.BasisZ);
			}
			else
			{
				if (!(wallAxis.GetType() == typeof(Arc)))
				{
					return Autodesk.Revit.UI.Result.Failed;
				}
				Arc arc = wallAxis as Arc;
				XYZ center = arc.Center;
				xyz3 = ArcAssistFunc.GetArcMidPoint(arc);
				XYZ xyz5 = (center - xyz3).Normalize();
				if ((center - xyz3).GetLength() < (center - new XYZ(pickPoint.X, pickPoint.Y, center.Z)).GetLength())
				{
					isWithin = false;
					xyz5 = -xyz5;
				}
				XYZ xyz6 = xyz5 * (wallThickness / 2.0 + num);
				xyz3 += xyz6;
				xyz = this.RotateTo(xyz5, -Math.PI*.5, XYZ.BasisZ);
				xyz2 = this.RotateTo(xyz5, Math.PI*.5, XYZ.BasisZ);
			}
			Transaction transaction = new Transaction(this.m_doc, "temp");
			transaction.Start();
			List<Element> list = new List<Element>();
			XYZ startPoint = xyz3 + xyz * num;
			XYZ xyz7 = xyz3 + xyz * num2;
			Line line = YJKLineEx.YJKGetBound(startPoint, xyz7);
			DetailCurve detailCurve = this.m_doc.Create.NewDetailCurve(this.m_doc.ActiveView, line);
			list.Add(detailCurve);
			XYZ xyz8 = this.RotateTo(xyz, 2.617993877991494, XYZ.BasisZ);
			Line line2 = YJKLineEx.YJKGetBound(xyz7, xyz7 + xyz8 * num);
			DetailCurve detailCurve2 = this.m_doc.Create.NewDetailCurve(this.m_doc.ActiveView, line2);
			list.Add(detailCurve2);
			XYZ xyz9 = this.RotateTo(xyz, -2.617993877991494, XYZ.BasisZ);
			Line line3 = YJKLineEx.YJKGetBound(xyz7, xyz7 + xyz9 * num);
			DetailCurve detailCurve3 = this.m_doc.Create.NewDetailCurve(this.m_doc.ActiveView, line3);
			list.Add(detailCurve3);
			XYZ startPoint2 = xyz3 + xyz2 * num;
			XYZ xyz10 = xyz3 + xyz2 * num2;
			Line line4 = YJKLineEx.YJKGetBound(startPoint2, xyz10);
			DetailCurve detailCurve4 = this.m_doc.Create.NewDetailCurve(this.m_doc.ActiveView, line4);
			list.Add(detailCurve4);
			XYZ xyz11 = this.RotateTo(xyz2, 2.617993877991494, XYZ.BasisZ);
			Line line5 = YJKLineEx.YJKGetBound(xyz10, xyz10 + xyz11 * num);
			DetailCurve detailCurve5 = this.m_doc.Create.NewDetailCurve(this.m_doc.ActiveView, line5);
			list.Add(detailCurve5);
			XYZ xyz12 = this.RotateTo(xyz2, -2.617993877991494, XYZ.BasisZ);
			Line line6 = YJKLineEx.YJKGetBound(xyz10, xyz10 + xyz12 * num);
			DetailCurve detailCurve6 = this.m_doc.Create.NewDetailCurve(this.m_doc.ActiveView, line6);
			list.Add(detailCurve6);
			Reference reference = null;
			try
			{
				reference = this.m_uiDoc.Selection.PickObject(Autodesk.Revit.UI.Selection.ObjectType.Element, new DetailCurveFilter(), "选择开门方向提示箭头");
			}
			catch (Exception)
			{
				transaction.RollBack();
				return Autodesk.Revit.UI.Result.Cancelled;
			}
			Element element = this.m_doc.GetElement(reference);
			if (element.Id.IntegerValue == detailCurve.Id.IntegerValue || element.Id.IntegerValue == detailCurve2.Id.IntegerValue || element.Id.IntegerValue == detailCurve3.Id.IntegerValue)
			{
				nearbyStart = xyz.Normalize();
			}
			else
			{
				if (element.Id.IntegerValue != detailCurve4.Id.IntegerValue && element.Id.IntegerValue != detailCurve5.Id.IntegerValue && element.Id.IntegerValue != detailCurve6.Id.IntegerValue)
				{
					transaction.RollBack();
					return Autodesk.Revit.UI.Result.Failed;
				}
				nearbyStart = xyz2.Normalize();
			}
			this.m_doc.DeleteElement(detailCurve);
			this.m_doc.DeleteElement(detailCurve4);
			this.m_doc.DeleteElement(detailCurve2);
			this.m_doc.DeleteElement(detailCurve3);
			this.m_doc.DeleteElement(detailCurve5);
			this.m_doc.DeleteElement(detailCurve6);
			transaction.Commit();
			return Autodesk.Revit.UI.Result.Succeeded;
		}

		private void DoInsertTag(FamilyInstance familyInstance)
		{
			if (!this.AddTag)
			{
				return;
			}
			try
			{
				if (familyInstance != null)
				{
                    if (familyInstance.Category.Id.IntegerValue == (int)BuiltInCategory.OST_Doors)
					{
						ImpDoorWinTagInsert.Do(this.m_uiDoc, familyInstance, this.m_TagFamilysymbol.Id);
					}
                    else if (familyInstance.Category.Id.IntegerValue == (int)BuiltInCategory.OST_Windows)
					{
						ImpDoorWinTagInsert.Do(this.m_uiDoc, familyInstance, this.m_TagFamilysymbol.Id);
					}
				}
			}
			catch
			{
			}
		}

		public UIApplication m_uiApp;

		public UIDocument m_uiDoc;

		public Application m_app;

		public Document m_doc;

		private DoorWinDatum m_datum;

		private bool m_AddTag;

		private FamilySymbol m_TagFamilysymbol;

		private string m_FirstTagString = "";

		private string m_SecondTagString = "";
	}
}
